package com.tcm.smarthealth.security;

import com.tcm.smarthealth.common.exception.BusinessException;
import com.tcm.smarthealth.config.JwtProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;

@Component
public class JwtAuthenticationInterceptor implements HandlerInterceptor {

    private static final List<String> WHITELIST = Arrays.asList(
            "/api/v1/auth/login",
            "/api/v1/auth/register",
            "/api/v1/health",
            "/error",
            "/swagger-ui.html",
            "/swagger-ui/**",
            "/v3/api-docs/**"
    );

    private final JwtTokenProvider jwtTokenProvider;
    private final JwtProperties jwtProperties;
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    public JwtAuthenticationInterceptor(JwtTokenProvider jwtTokenProvider, JwtProperties jwtProperties) {
        this.jwtTokenProvider = jwtTokenProvider;
        this.jwtProperties = jwtProperties;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (isWhitelisted(request)) {
            return true;
        }

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return true;
        }

        String header = request.getHeader(jwtProperties.getHeader());
        if (!StringUtils.hasText(header) || !header.startsWith(jwtProperties.getTokenPrefix())) {
            throw new BusinessException(HttpStatus.UNAUTHORIZED, "缺少或非法的身份认证信息");
        }

        String token = header.substring(jwtProperties.getTokenPrefix().length()).trim();
        try {
            Jws<Claims> parsed = jwtTokenProvider.validateAndParse(token);
            Claims claims = parsed.getBody();
            Long userId = Long.valueOf(claims.getSubject());
            String username = claims.get("username", String.class);
            String role = claims.get("role", String.class);

            AuthenticatedUser user = new AuthenticatedUser(userId, username, role);
            AuthContext.setCurrentUser(user);
            request.setAttribute("CURRENT_USER", user);
            return true;
        } catch (Exception ex) {
            throw new BusinessException(HttpStatus.UNAUTHORIZED, "身份认证已失效，请重新登录");
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        AuthContext.clear();
    }

    private boolean isWhitelisted(HttpServletRequest request) {
        String path = request.getRequestURI();
        return WHITELIST.stream().anyMatch(pattern -> pathMatcher.match(pattern, path));
    }
}

